OpenCV Canny边缘检测器

您所在的位置:网站首页 opencv canny边缘检测算法 OpenCV Canny边缘检测器

OpenCV Canny边缘检测器

2023-03-20 22:40| 来源: 网络整理| 查看: 265

目标

在本教程中,您将学习如何:

使用OpenCV函数cv :: Canny来实现Canny Edge Detector。理论

该Canny边缘检测是由约翰·F·坎尼在1986年也知道很多的开发最佳的检测,坎尼算法旨在满足三个主要标准:

低错误率:意味着只有现有边缘的良好检测。良好的定位:检测到的边缘像素与实际边缘像素之间的距离必须最小化。最小响应:每个边缘只有一个检测器响应。步骤滤除任何噪音。高斯滤波器用于此目的。可能使用的的高斯内核的示例如下所示:size=5

Canny边缘检测器

找到图像的强度梯度。为此,我们遵循类似于Sobel的程序:

应用一对卷积面罩 (在 x 和 y directions:

Canny边缘检测器

查找梯度强度和方向:

Canny边缘检测器

方向四舍五入为四个可能的角度之一(即0,45,90或135)

应用非最大抑制。这将删除不被认为是边缘的一部分的像素。因此,只有细线(候选边)将保留。滞后:最后一步。Canny确实使用两个阈值(上限和下限):如果像素梯度高于上限阈值,则像素被接受为边缘如果像素梯度值低于较低阈值,则会被拒绝。如果像素梯度在两个阈值之间,那么只有当它连接到高于上限阈值的像素时才被接受。

Canny推荐上限:2:1和3:1之间的较低比例。

有关更多详细信息,您可以随时咨询您最喜爱的Computer Vision书籍。Code这个程序是做什么的?要求用户输入数值以设置我们的Canny Edge Detector的下限(通过Trackbar)。应用Canny Detector并生成一个蒙版(亮线表示黑色背景上的边缘)。应用在原始图像上获得的蒙版,并将其显示在窗口中。教程代码如下所示。您也可以从这里下载 #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" using namespace cv; Mat src, src_gray; Mat dst, detected_edges; int edgeThresh = 1; int lowThreshold; int const max_lowThreshold = 100; int ratio = 3; int kernel_size = 3; const char* window_name = "Edge Map"; static void CannyThreshold(int, void*) { blur( src_gray, detected_edges, Size(3,3) ); Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size ); dst = Scalar::all(0); src.copyTo( dst, detected_edges); imshow( window_name, dst ); } int main( int, char** argv ) { src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; } dst.create( src.size(), src.type() ); cvtColor( src, src_gray, COLOR_BGR2GRAY ); namedWindow( window_name, WINDOW_AUTOSIZE ); createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold ); CannyThreshold(0, 0); waitKey(0); return 0; }说明创建一些必需的变量:Mat src, src_gray; Mat dst, detected_edges; int edgeThresh = 1; int lowThreshold; int const max_lowThreshold = 100; int ratio = 3; int kernel_size = 3; const char* window_name = "Edge Map";

请注意以下事项:

我们建立一个较低的上限阈值3:1(与可变比率)的比率。我们设置内核大小为(Sobel操作由Canny函数内部执行)。3我们为的下限阈值设置最大值。100加载源图像: src = imread( argv[1], IMREAD_COLOR ); // Load an image if( src.empty() ) { return -1; }创建一个相同类型和大小的src(为dst)的矩阵: dst.create(src.size(),src.type()); 将图像转换为灰度级(使用函数cv :: cvtColor): cvtColor(src,src_gray,COLOR_BGR2GRAY); 创建一个窗口来显示结果: namedWindow(window_name,WINDOW_AUTOSIZE); 创建一个跟踪栏,供用户输入Canny检测器的下限: createTrackbar(“Min Threshold:”,window_name,&lowThreshold,max_lowThreshold,CannyThreshold);

观察以下内容:

Trackbar要控制的变量是lowThreshold,最大值为max_lowThreshold(我们先前设置为100)每次Trackbar注册一个动作时,将调用回调函数CannyThreshold。让我们检查CannyThreshold函数,一步一步:首先,我们用内核大小为3的过滤器模糊图像:     blur(src_gray,detected_edges,Size(3,3)); 然后,我们应用OpenCV函数cv :: Canny: Canny(detected_edges,detected_edges,lowThreshold,lowThreshold * ratio,kernel_size);

其中的解释:

detected_edges:源图像,灰度detected_edges:检测器的输出(可以与输入相同)lowThreshold:用户移动轨迹栏输入的值highThreshold:在程序中设置为下限阈值的三倍(在Canny的建议之后)kernel_size:我们将它定义为3(要在内部使用的Sobel内核的大小)我们用零填充dst图像(意味着图像是完全黑色的)。 dst = Scalar :: all(0); 最后,我们将使用函数cv :: Mat :: copyTo仅映射被识别为边缘的图像的区域(在黑色背景上)。cv :: Mat :: copy将src映像复制到dst上。但是,它只会复制它们具有非零值的位置中的像素。由于Canny检测器的输出是黑色背景上的边缘轮廓,因此所得到的dst在所有区域都将为黑色,但检测到的边缘为黑色。 src.copyTo(dst,detected_edges); 我们显示结果: imshow(window_name,dst); 结果在编译上面的代码之后,我们可以运行它作为参数作为图像的路径。例如,使用以下图像作为输入:

Canny边缘检测器

移动滑块,尝试不同的阈值,我们得到以下结果:

Canny边缘检测器

注意图像如何与边缘区域上的黑色背景叠加。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3